package com.fgba.express.data.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fgba.express.comm.enums.MenuType;
import com.fgba.express.comm.enums.State;
import com.fgba.express.core.service.impl.CrudServiceImpl;
import com.fgba.express.data.dao.IMenuDao;
import com.fgba.express.data.dao.IRoleMenuMappingDao;
import com.fgba.express.data.dto.MenuDto;
import com.fgba.express.data.entity.Menu;
import com.fgba.express.data.entity.Role;
import com.fgba.express.data.entity.RoleMenuMapping;
import com.fgba.express.data.entity.UserRoleMapping;
import com.fgba.express.data.mapstruct.MenuStruct;
import com.fgba.express.data.search.MenuSearch;
import com.fgba.express.data.service.IMenuService;
import com.fgba.express.data.service.IRoleService;
import com.fgba.express.data.service.IUserRoleMappingService;
import com.fgba.express.util.BeanContextUtil;
import com.fgba.express.util.NullChecker;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 * 菜单 服务实现类
 * </p>
 *
 * @author fgba
 * @since 2022-02-24
 */
@Service("menuServiceImpl")
public class MenuServiceImpl extends CrudServiceImpl<IMenuDao, Menu, MenuDto, MenuSearch, MenuStruct> implements IMenuService {

    @Override
    public boolean removeById(Serializable id) {
        Menu menu = baseMapper.selectById(id);
        menu.setState(State.STATUS_DELETE);
        menu.setModifiedTime(LocalDateTime.now());
        baseMapper.updateById(menu);
        return true;
    }

    @Override
    public boolean removeByIds(Collection<? extends Serializable> idList) {
        List<Menu> menus = baseMapper.selectBatchIds(idList);
        boolean flag = true;
        for (Menu menu : menus) {
            menu.setState(State.STATUS_DELETE);
            menu.setModifiedTime(LocalDateTime.now());

            if (baseMapper.updateById(menu) <= 0) {
                flag = false;
            }
        }
        return flag;
    }

    @Override
    public List<MenuDto> getMenuByRoleId(Long roleId) {
        List<RoleMenuMapping> roleMenuMappings = BeanContextUtil.getBean(IRoleMenuMappingDao.class).selectList(Wrappers.<RoleMenuMapping>query().select("distinct menu_id").eq(!NullChecker.isNullOrZero(roleId), "role_id", roleId));
        List<Long> menuIds = roleMenuMappings.stream().map(RoleMenuMapping::getMenuId).collect(Collectors.toList());
        List<Menu> menus = list();
        List<MenuDto> menuDTOs = struct.dtoConvertEntity(menus);
        for (MenuDto menuDTO : menuDTOs) {
            boolean selected = menuIds.contains(menuDTO.getId());
            menuDTO.setChecked(selected);
        }
        return menuDTOs;
    }

    @Override
    public List<MenuDto> getNavMenus(Long userId) {
        if (NullChecker.isNullOrZero(userId)) {
            return new ArrayList<>();
        }
        LambdaQueryWrapper<UserRoleMapping> userRoleMappingLambdaQueryWrapper = Wrappers.<UserRoleMapping>lambdaQuery().select(UserRoleMapping::getRoleId).eq(UserRoleMapping::getUserId, userId);
        List<Long> roleIds = BeanContextUtil.getBean(IUserRoleMappingService.class).list(userRoleMappingLambdaQueryWrapper).stream().map(UserRoleMapping::getRoleId).collect(Collectors.toList());
        List<Role> roles = BeanContextUtil.getBean(IRoleService.class).list(Wrappers.<Role>lambdaQuery().in(Role::getId, roleIds));
        if (NullChecker.isNull(roles)) {
            return new ArrayList<>();
        }
        List<RoleMenuMapping> roleMenuMappings = BeanContextUtil.getBean(IRoleMenuMappingDao.class)
                .selectList(Wrappers.<RoleMenuMapping>query()
                        .select("distinct menu_id")
                        .in("role_id", roles.stream().map(Role::getId).collect(Collectors.toList())));

        if (NullChecker.isNull(roleMenuMappings)) {
            return new ArrayList<>();
        }

        List<Menu> menus = BeanContextUtil.getBean(IMenuService.class)
                .listByIds(roleMenuMappings.stream()
                        .map(RoleMenuMapping::getMenuId)
                        .collect(Collectors.toList()));
        return struct.dtoConvertEntity(menus);
    }

    @Override
    public List<String> getConfigAttributes() {
        List<Menu> menus = this.list(Wrappers.<Menu>lambdaQuery().eq(Menu::getState, State.STATUS_AVAILABLE.getCode()));
        List<String> perms = menus.stream().map(Menu::getPerms).collect(Collectors.toList());
        return perms;
    }

    @Override
    public List<MenuDto> getList(MenuSearch search) {
        List<Menu> menus = list(Wrappers.<Menu>lambdaQuery().
                like(!NullChecker.isNullOrEmpty(search.getName()), Menu::getName, search.getName()).
                like(!NullChecker.isNullOrEmpty(search.getPerms()), Menu::getPerms, search.getPerms()));

        return struct.dtoConvertEntity(menus);
    }
}
